package com.kexilo.dict.properties;

import java.time.Duration;
import java.util.ArrayList;
import java.util.List;

import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.context.properties.NestedConfigurationProperty;

import jakarta.validation.Valid;
import jakarta.validation.constraints.Min;
import jakarta.validation.constraints.NotBlank;

/**
 * 字典插件配置属性
 * 提供完善的配置选项和IDE智能提示
 * 
 * @author Kexilo
 */
@ConfigurationProperties(prefix = "kexilo.plugin.dict")
public class DictProperties {
    
    /**
     * 缓存策略
     */
    public enum CacheStrategy {
        NONE,       // 不缓存
        LOCAL,      // 本地缓存
        REDIS,      // Redis缓存
        HYBRID      // 混合缓存（本地+Redis）
    }
    
    /**
     * 数据源类型
     */
    public enum DataSourceType {
        DATABASE,   // 数据库
        API,        // 外部API
        FILE,       // 文件
        CUSTOM      // 自定义
    }
    
    /**
     * 是否启用字典插件
     */
    private boolean enabled = true;
    
    /**
     * 数据源类型
     */
    private DataSourceType dataSourceType = DataSourceType.DATABASE;
    
    /**
     * 缓存策略
     */
    private CacheStrategy cacheStrategy = CacheStrategy.LOCAL;
    
    /**
     * 是否启用预热
     */
    private boolean warmupEnabled = true;
    
    /**
     * 预热的字典类型
     */
    private List<String> warmupTypes = new ArrayList<>();
    
    /**
     * 是否启用异步加载
     */
    private boolean asyncEnabled = true;
    
    /**
     * 数据库配置
     */
    @Valid
    @NestedConfigurationProperty
    private DatabaseProperties database = new DatabaseProperties();
    
    /**
     * 缓存配置
     */
    @Valid
    @NestedConfigurationProperty
    private CacheProperties cache = new CacheProperties();
    
    /**
     * API配置
     */
    @Valid
    @NestedConfigurationProperty
    private ApiProperties api = new ApiProperties();
    
    /**
     * 监控配置
     */
    @Valid
    @NestedConfigurationProperty
    private MonitorProperties monitor = new MonitorProperties();
    
    /**
     * 数据库配置属性
     */
    public static class DatabaseProperties {
        /**
         * 字典数据表名
         */
        @NotBlank(message = "字典数据表名不能为空")
        private String dictDataTable = "sys_dict_data";
        
        /**
         * 字典类型表名
         */
        @NotBlank(message = "字典类型表名不能为空")
        private String dictTypeTable = "sys_dict_type";
        
        /**
         * 查询超时时间
         */
        private Duration queryTimeout = Duration.ofSeconds(30);
        
        /**
         * 是否启用批量查询
         */
        private boolean batchQueryEnabled = true;
        
        /**
         * 批量查询大小
         */
        @Min(value = 1, message = "批量查询大小必须大于0")
        private int batchSize = 50;
        
        // Getters and Setters
        public String getDictDataTable() { return dictDataTable; }
        public void setDictDataTable(String dictDataTable) { this.dictDataTable = dictDataTable; }
        
        public String getDictTypeTable() { return dictTypeTable; }
        public void setDictTypeTable(String dictTypeTable) { this.dictTypeTable = dictTypeTable; }
        
        public Duration getQueryTimeout() { return queryTimeout; }
        public void setQueryTimeout(Duration queryTimeout) { this.queryTimeout = queryTimeout; }
        
        public boolean isBatchQueryEnabled() { return batchQueryEnabled; }
        public void setBatchQueryEnabled(boolean batchQueryEnabled) { this.batchQueryEnabled = batchQueryEnabled; }
        
        public int getBatchSize() { return batchSize; }
        public void setBatchSize(int batchSize) { this.batchSize = batchSize; }
    }
    
    /**
     * 缓存配置属性
     */
    public static class CacheProperties {
        /**
         * 缓存名称
         */
        private String cacheName = "kexilo-dict";
        
        /**
         * 缓存键前缀
         */
        private String keyPrefix = "dict:";
        
        /**
         * 缓存过期时间
         */
        private Duration expiry = Duration.ofHours(2);
        
        /**
         * 本地缓存最大条目数
         */
        @Min(value = 1, message = "本地缓存最大条目数必须大于0")
        private int localMaxSize = 1000;
        
        /**
         * 缓存刷新间隔
         */
        private Duration refreshInterval = Duration.ofMinutes(30);
        
        /**
         * 是否启用缓存统计
         */
        private boolean statsEnabled = true;
        
        /**
         * 是否启用空值缓存（防止缓存穿透）
         */
        private boolean cacheNullValues = true;
        
        /**
         * 空值缓存过期时间
         */
        private Duration nullValueExpiry = Duration.ofMinutes(5);
        
        // Getters and Setters
        public String getCacheName() { return cacheName; }
        public void setCacheName(String cacheName) { this.cacheName = cacheName; }
        
        public String getKeyPrefix() { return keyPrefix; }
        public void setKeyPrefix(String keyPrefix) { this.keyPrefix = keyPrefix; }
        
        public Duration getExpiry() { return expiry; }
        public void setExpiry(Duration expiry) { this.expiry = expiry; }
        
        public int getLocalMaxSize() { return localMaxSize; }
        public void setLocalMaxSize(int localMaxSize) { this.localMaxSize = localMaxSize; }
        
        public Duration getRefreshInterval() { return refreshInterval; }
        public void setRefreshInterval(Duration refreshInterval) { this.refreshInterval = refreshInterval; }
        
        public boolean isStatsEnabled() { return statsEnabled; }
        public void setStatsEnabled(boolean statsEnabled) { this.statsEnabled = statsEnabled; }
        
        public boolean isCacheNullValues() { return cacheNullValues; }
        public void setCacheNullValues(boolean cacheNullValues) { this.cacheNullValues = cacheNullValues; }
        
        public Duration getNullValueExpiry() { return nullValueExpiry; }
        public void setNullValueExpiry(Duration nullValueExpiry) { this.nullValueExpiry = nullValueExpiry; }
    }
    
    /**
     * API配置属性
     */
    public static class ApiProperties {
        /**
         * API基础URL
         */
        private String baseUrl;
        
        /**
         * 连接超时
         */
        private Duration connectTimeout = Duration.ofSeconds(10);
        
        /**
         * 读取超时
         */
        private Duration readTimeout = Duration.ofSeconds(30);
        
        /**
         * 重试次数
         */
        @Min(value = 0, message = "重试次数不能小于0")
        private int retryCount = 3;
        
        /**
         * 重试间隔
         */
        private Duration retryInterval = Duration.ofSeconds(1);
        
        /**
         * API密钥
         */
        private String apiKey;
        
        /**
         * 是否启用API调用日志
         */
        private boolean loggingEnabled = false;
        
        // Getters and Setters
        public String getBaseUrl() { return baseUrl; }
        public void setBaseUrl(String baseUrl) { this.baseUrl = baseUrl; }
        
        public Duration getConnectTimeout() { return connectTimeout; }
        public void setConnectTimeout(Duration connectTimeout) { this.connectTimeout = connectTimeout; }
        
        public Duration getReadTimeout() { return readTimeout; }
        public void setReadTimeout(Duration readTimeout) { this.readTimeout = readTimeout; }
        
        public int getRetryCount() { return retryCount; }
        public void setRetryCount(int retryCount) { this.retryCount = retryCount; }
        
        public Duration getRetryInterval() { return retryInterval; }
        public void setRetryInterval(Duration retryInterval) { this.retryInterval = retryInterval; }
        
        public String getApiKey() { return apiKey; }
        public void setApiKey(String apiKey) { this.apiKey = apiKey; }
        
        public boolean isLoggingEnabled() { return loggingEnabled; }
        public void setLoggingEnabled(boolean loggingEnabled) { this.loggingEnabled = loggingEnabled; }
    }
    
    /**
     * 监控配置属性
     */
    public static class MonitorProperties {
        /**
         * 是否启用性能监控
         */
        private boolean enabled = true;
        
        /**
         * 慢查询阈值
         */
        private Duration slowQueryThreshold = Duration.ofMillis(1000);
        
        /**
         * 是否启用缓存命中率监控
         */
        private boolean cacheHitRateEnabled = true;
        
        /**
         * 监控数据保留时间
         */
        private Duration dataRetentionTime = Duration.ofDays(7);
        
        /**
         * 是否启用告警
         */
        private boolean alertEnabled = false;
        
        /**
         * 缓存命中率告警阈值
         */
        @Min(value = 0, message = "告警阈值不能小于0")
        private double hitRateAlertThreshold = 0.8;
        
        // Getters and Setters
        public boolean isEnabled() { return enabled; }
        public void setEnabled(boolean enabled) { this.enabled = enabled; }
        
        public Duration getSlowQueryThreshold() { return slowQueryThreshold; }
        public void setSlowQueryThreshold(Duration slowQueryThreshold) { this.slowQueryThreshold = slowQueryThreshold; }
        
        public boolean isCacheHitRateEnabled() { return cacheHitRateEnabled; }
        public void setCacheHitRateEnabled(boolean cacheHitRateEnabled) { this.cacheHitRateEnabled = cacheHitRateEnabled; }
        
        public Duration getDataRetentionTime() { return dataRetentionTime; }
        public void setDataRetentionTime(Duration dataRetentionTime) { this.dataRetentionTime = dataRetentionTime; }
        
        public boolean isAlertEnabled() { return alertEnabled; }
        public void setAlertEnabled(boolean alertEnabled) { this.alertEnabled = alertEnabled; }
        
        public double getHitRateAlertThreshold() { return hitRateAlertThreshold; }
        public void setHitRateAlertThreshold(double hitRateAlertThreshold) { this.hitRateAlertThreshold = hitRateAlertThreshold; }
    }
    
    // Main class Getters and Setters
    public boolean isEnabled() { return enabled; }
    public void setEnabled(boolean enabled) { this.enabled = enabled; }
    
    public DataSourceType getDataSourceType() { return dataSourceType; }
    public void setDataSourceType(DataSourceType dataSourceType) { this.dataSourceType = dataSourceType; }
    
    public CacheStrategy getCacheStrategy() { return cacheStrategy; }
    public void setCacheStrategy(CacheStrategy cacheStrategy) { this.cacheStrategy = cacheStrategy; }
    
    public boolean isWarmupEnabled() { return warmupEnabled; }
    public void setWarmupEnabled(boolean warmupEnabled) { this.warmupEnabled = warmupEnabled; }
    
    public List<String> getWarmupTypes() { return warmupTypes; }
    public void setWarmupTypes(List<String> warmupTypes) { this.warmupTypes = warmupTypes; }
    
    public boolean isAsyncEnabled() { return asyncEnabled; }
    public void setAsyncEnabled(boolean asyncEnabled) { this.asyncEnabled = asyncEnabled; }
    
    public DatabaseProperties getDatabase() { return database; }
    public void setDatabase(DatabaseProperties database) { this.database = database; }
    
    public CacheProperties getCache() { return cache; }
    public void setCache(CacheProperties cache) { this.cache = cache; }
    
    public ApiProperties getApi() { return api; }
    public void setApi(ApiProperties api) { this.api = api; }
    
    public MonitorProperties getMonitor() { return monitor; }
    public void setMonitor(MonitorProperties monitor) { this.monitor = monitor; }
}
